package com.xu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.xu.base.enums.ResponseCodeEnum;
import com.xu.base.model.BaseSelectVo;
import com.xu.base.utils.AssertUtils;
import com.xu.base.utils.TreeNodeUtils;
import com.xu.mybatis.model.PageInfo;
import com.xu.redis.service.SequenceService;
import com.xu.security.utils.SecurityUtils;
import com.xu.system.constant.Constants;
import com.xu.system.enums.SequenceEnum;
import com.xu.system.model.convert.DeptConvert;
import com.xu.system.model.entity.SysDept;
import com.xu.system.model.pojo.dept.*;
import com.xu.system.service.IDeptService;
import com.xu.system.service.db.ISysDeptService;
import com.xu.system.service.db.ISysUserDeptService;
import com.xu.system.service.db.ISysUserService;
import jakarta.annotation.Resource;
import org.apache.commons.collections.ListUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: 许乾伟
 * @Date: 2024/12/17 16:49
 */
@Service
public class DeptServiceImpl implements IDeptService {
    @Resource
    ISysDeptService sysDeptService;
    @Resource
    ISysUserService sysUserService;
    @Resource
    ISysUserDeptService sysUserDeptService;
    @Resource
    DeptConvert deptConvert;
    @Resource
    SequenceService sequenceService;
    @Override
    public Boolean add(AddDeptReq req) {
        verifyDeptName(req.getDeptName(),null);
        SysDept sysDept = deptConvert.toSysDept(req);
        //生成编号
        sysDept.setDeptCode(sequenceService.generateCode(SequenceEnum.DEPT_CODE_RULE));
        boolean save = sysDeptService.save(sysDept);
        AssertUtils.isFalse(save, ResponseCodeEnum.HANDEL_FAILED, "新增部门失败");
        //新增用户部门关联
        Boolean flag = sysUserDeptService.saveUserDept(req.getLeaderUserId(), sysDept.getId());
        AssertUtils.isFalse(flag, ResponseCodeEnum.HANDEL_FAILED, "新增部门失败");
        return Boolean.TRUE;
    }

    @Override
    public Boolean edit(EditDeptReq req) {
        SysDept sysDept = sysDeptService.getById(req.getDeptId());
        AssertUtils.isNull(sysDept, ResponseCodeEnum.DATA_FAILED, "未查询到部门数据，无法编辑");
        verifyDeptName(req.getDeptName(), req.getDeptId());
        sysDept.setDeptName(req.getDeptName().trim());
        sysDept.setLeaderUserId(req.getLeaderUserId());
        sysDept.setSort(req.getSort());
        if (sysDept.getStatus() && !req.getStatus()) {
            //停用子部门
            List<SysDept> childDeptList = sysDeptService.getChildDeptList(req.getDeptId());
            if (!CollectionUtils.isEmpty(childDeptList)) {
                childDeptList.forEach(n -> {
                    n.setStatus(req.getStatus());
                });
                sysDeptService.updateBatchById(childDeptList);
            }
        }
        if (req.getStatus() && req.getParentId() != null && !Constants.TREE_ROOT_ID.equals(req.getParentId())) {
            //判断上级部门状态
            SysDept parentDept = sysDeptService.getById(req.getParentId());
            AssertUtils.isFalse(parentDept.getStatus(), ResponseCodeEnum.HANDEL_FAILED, "上级部门已停用，无法启用");
        }
        sysDept.setStatus(req.getStatus());
        sysDept.setRemark(req.getRemark());
        sysDept.setUpdateBy(SecurityUtils.getUserId());
        sysDept.setUpdateTime(LocalDateTime.now());
        boolean update = sysDeptService.updateById(sysDept);
        AssertUtils.isFalse(update, ResponseCodeEnum.HANDEL_FAILED, "编辑部门失败");
        return Boolean.TRUE;
    }

    @Override
    public Boolean del(Long deptId) {
        SysDept sysDept = sysDeptService.getById(deptId);
        AssertUtils.isNull(sysDept, ResponseCodeEnum.DATA_FAILED, "未查询到部门数据，无法删除");
        AssertUtils.isTrue(sysUserDeptService.isUse(deptId), ResponseCodeEnum.HANDEL_FAILED, "部门已经被使用,无法删除");
        sysDept.setIsDelete(Boolean.TRUE)
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysDeptService.updateById(sysDept);
    }

    @Override
    public DeptVo detail(Long deptId) {
        SysDept sysDept = sysDeptService.getById(deptId);
        AssertUtils.isNull(sysDept, ResponseCodeEnum.DATA_FAILED, "未查询到部门数据");
        return deptConvert.toDeptVo(sysDept);
    }

    @Override
    public PageInfo<DeptSimpleVo> pageInfo(QueryDeptReq req) {
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        List<SysDept> list = searchList(req);
        PageInfo<SysDept> pageData = new PageInfo<>(list);
        //获取用户名称翻译
        List<Long> leaderIds = list.stream().map(SysDept::getLeaderUserId).distinct().collect(Collectors.toList());
        List<Long> userIds = list.stream().flatMap(n -> Stream.of(n.getCreateBy(), n.getUpdateBy())).distinct().collect(Collectors.toList());
        //获取成员数量
        List<Long> deptIds = list.stream().map(SysDept::getId).collect(Collectors.toList());
        return deptConvert.toDeptSimpleVoPage(pageData,sysUserService.getUserNameMap(ListUtils.union(leaderIds,userIds)),sysUserDeptService.getUserCount(deptIds));
    }

    @Override
    public List<BaseSelectVo<Long, String>> allSelectList() {
        QueryWrapper<SysDept> wrapper = new QueryWrapper<>();
        wrapper.eq(SysDept.IS_DELETE, Boolean.FALSE);
        List<SysDept> list = sysDeptService.list(wrapper);
        if (CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        return list.stream().map(item -> new BaseSelectVo<>(item.getId(), item.getDeptName())).collect(Collectors.toList());
    }

    @Override
    public List<DeptSimpleVo> all(QueryDeptReq req) {
        List<SysDept> list = searchList(req);
        //获取用户名称翻译
        List<Long> leaderIds = list.stream().map(SysDept::getLeaderUserId).distinct().collect(Collectors.toList());
        List<Long> userIds = list.stream().flatMap(n -> Stream.of(n.getCreateBy(), n.getUpdateBy())).distinct().collect(Collectors.toList());
        //获取成员数量
        List<Long> deptIds = list.stream().map(SysDept::getId).collect(Collectors.toList());
        return deptConvert.toDeptSimpleVoList(list,sysUserService.getUserNameMap(ListUtils.union(leaderIds,userIds)),sysUserDeptService.getUserCount(deptIds));
    }

    @Override
    public List<DeptSimpleTreeVo> tree(QueryDeptReq req) {
        List<SysDept> list = searchList(req);
        if (CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        //获取用户名称翻译
        List<Long> leaderIds = list.stream().map(SysDept::getLeaderUserId).distinct().collect(Collectors.toList());
        List<Long> userIds = list.stream().flatMap(n -> Stream.of(n.getCreateBy(), n.getUpdateBy())).distinct().collect(Collectors.toList());
        //获取成员数量
        List<Long> deptIds = list.stream().map(SysDept::getId).collect(Collectors.toList());
        List<DeptSimpleTreeVo> result = deptConvert.toDeptSimpleTreeVoList(list, sysUserService.getUserNameMap(ListUtils.union(leaderIds, userIds)), sysUserDeptService.getUserCount(deptIds));
        return TreeNodeUtils.buildTree(result);
    }

    /**
     * 部门名称去重校验
     * @param deptName
     * @param deptId
     */
    private void verifyDeptName(String deptName, Long deptId) {
        long count = sysDeptService.count(new QueryWrapper<SysDept>()
                .ne(deptId!=null, SysDept.ID,deptId)
                .eq(SysDept.DEPT_NAME,deptName)
                .eq(SysDept.IS_DELETE,Boolean.FALSE));
        AssertUtils.isTrue(count>0, ResponseCodeEnum.DATA_FAILED,"部门名称已存在,请检查!");
    }

    /**
     * 查询列表
     * @param req
     * @return
     */
    private List<SysDept> searchList(QueryDeptReq req){
        QueryWrapper<SysDept> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.hasText(req.getDeptName()), SysDept.DEPT_NAME, req.getDeptName())
                .eq(req.getLeaderUserId() != null, SysDept.LEADER_USER_ID, req.getLeaderUserId())
                .eq(req.getStatus() != null, SysDept.STATUS, req.getStatus())
                .ge(StringUtils.hasText(req.getStartTime()), SysDept.UPDATE_TIME, req.getStartTime())
                .le(StringUtils.hasText(req.getEndTime()), SysDept.UPDATE_TIME, req.getEndTime())
                .eq(SysDept.IS_DELETE, Boolean.FALSE)
                .orderByDesc(SysDept.UPDATE_TIME);
        List<SysDept> list = sysDeptService.list(wrapper);
        return list;
    }
}
